package com.efast.cafe.portal.security.core.impl;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashSet;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.efast.cafe.commponent.log.ext.CafeLogger;
import com.efast.cafe.commponent.log.ext.CafeLoggerFactory;
import com.efast.cafe.framework.constant.CommonConstant;
import com.efast.cafe.framework.constant.SecurityConstant;
import com.efast.cafe.portal.bean.common.PortalUserDetails;
import com.efast.cafe.portal.bean.common.PortalUserSecurityBean;
import com.efast.cafe.portal.bean.common.WeixinResult;
import com.efast.cafe.portal.security.core.AuthenticationTypeService;
import com.efast.cafe.portal.service.common.IResourceService;
import com.efast.cafe.util.ConfigUtil;
import com.efast.cafe.util.HttpClientUtils;

@Component("wechatAuthenticationProcessor")
public class WechatAuthenticationProcessor extends PwdAuthenticationProcessor implements AuthenticationTypeService{

	private CafeLogger logger = CafeLoggerFactory.getLogger(WechatAuthenticationProcessor.class);
	
	@Autowired
	private IResourceService portalResourceService;
	
	@Override
	public UsernamePasswordAuthenticationToken authentication(HttpServletRequest request) {
		String code = request.getParameter("code");
		//String companyCode = request.getParameter("companyCode");
		String companyCode = ConfigUtil.getValue("wechat.companyCode");
		JSONObject access = null;
		try{
			access = getAccessTokenAndOpenIdByCode(code,request);
		}catch(Exception e){
			logger.error("Get access_token and openid by code error.", e);
			throw new AuthenticationServiceException(SecurityConstant.ERROR_CODE.TOKEN_ERROR);
		}
		if(access==null){
			throw new AuthenticationServiceException(SecurityConstant.ERROR_CODE.TOKEN_ERROR);
		}
		String openid = access.getString("openid");
		
		HttpSession session = request.getSession();
		session.setAttribute(CommonConstant.WECHAT_OPENID, openid);
		
		String pwd = UUID.randomUUID().toString();
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				companyCode+CommonConstant.J_COMPANY_USERNAME_SEPARATOR+openid+CommonConstant.J_COMPANY_USERNAME_SEPARATOR+pwd, pwd);
		return authRequest;
		
	}

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
		HttpSession session = request.getSession();
		PortalUserDetails userDetail = (PortalUserDetails)authentication.getPrincipal();
		PortalUserSecurityBean user = userDetail.getUser();
		JSONObject res = new JSONObject();
		boolean needBindPhone = false;
		if(user.getPortal_company_user_id()==null){
			needBindPhone = true;
		}
		session.setAttribute(CommonConstant.PORTAL_USER_OBJECT, user);
		session.setAttribute(CommonConstant.CURRENT_LOGIN_USER_NAME_KEY, user.getUname());
		session.setAttribute(CommonConstant.CURRENT_LOGIN_USER_COMPANYCODE_KEY, user.getCompany_code());
		
		HashSet<String> checkauthSet = portalResourceService.queryPurviewPathByCompanyUserAndRoleDB(user.getCompany_code(), user.getUname());
		HashSet<String> allPurvewPathSet = portalResourceService.queryAllPurviewPathDB();
		
		session.setAttribute(CommonConstant.CURRENT_LOGIN_USER_PURVIEWSET_SESSIONKEY, checkauthSet);
		session.setAttribute(CommonConstant.CURRENT_LOGIN_USER_ALLPURVIEWSET_SESSIONKEY, allPurvewPathSet);
		
		res.put("needBindPhone", needBindPhone);//需要绑定手机号码
		res.put("phone", user.getPhone());
		res.put("firstName", user.getFirstName());
		res.put("lastName", user.getLastName());
		String token = UUID.randomUUID().toString();
		res.put("token", token);
		session.setAttribute("token", token);
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		response.getWriter().print(res.toString());
	}

	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		super.onAuthenticationFailure(request, response, exception);
	System.out.println("onAuthenticationFailure: " + exception.getMessage());
	System.out.println("onAuthenticationFailure: " + exception.getLocalizedMessage());
	}

	@Override
	public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException {
		//String companyCode = request.getParameter("companyCode");
		String type = request.getParameter("type");
		String appId = ConfigUtil.getValue("wechat.appid");
		String redirect_uri = URLEncoder.encode(ConfigUtil.getValue("wechat.redirect_uri."+type),"utf-8");
		//redirect_uri = "rm.test.efastserv.com/wechatAuthentication";
		StringBuilder sb = new StringBuilder("https://open.weixin.qq.com/connect/oauth2/authorize?")
				.append("appid=").append(appId)
				.append("&redirect_uri=").append(redirect_uri)
				.append("&response_type=code&scope=snsapi_userinfo").append("#wechat_redirect");
				//.append("&companyCode=").append(companyCode);
		System.out.println("redirect_uri-------------------------------------" + sb.toString());
		response.sendRedirect(sb.toString());
	}
	
	
	
	private JSONObject getAccessTokenAndOpenIdByCode(String code,HttpServletRequest request){
		//String companyCode = request.getParameter("companyCode");
		String appId = ConfigUtil.getValue("wechat.appid");
		String appSecret = ConfigUtil.getValue("wechat.secret");
		String url = String.format(
				"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
				appId, appSecret, code);
		WeixinResult wr = GetStrFromWeixinService(url, "", "Get");
		if (wr.getErrCode() == 0) {
			
			JSONObject json = JSON.parseObject(wr.getResult());
			return json;
		} else {
			return null;
		}
	}
	
	private JSONObject getUserInfoByTokenAndOpenId(String token,String openId){
		String url = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", token,openId);
		WeixinResult wr = GetStrFromWeixinService(url, "", "Get");
		if (wr.getErrCode() == 0) {
			JSONObject json = JSON.parseObject(wr.getResult());
			return json;
		} else {
			return null;
		}
	}
	
	
	private  WeixinResult GetStrFromWeixinService(String url, String PostData, String method) {
		WeixinResult result = new WeixinResult();
		result = WeixinResult.Success();
		if (url == null || method == null || url.isEmpty()
				|| ("Get".equalsIgnoreCase(method) && "Post".equalsIgnoreCase(method))) {
			result = WeixinResult.Fail("请求地址为空,或不支持的请求类型");
			return result;
		}
		// HttpClientUtils client = new HttpClientUtils();
		if ("Get".equalsIgnoreCase(method)) {
			result.setResult(HttpClientUtils.doGet(url, 5000));
		} else if ("Post".equalsIgnoreCase(method)) {
			result.setResult(HttpClientUtils.doPost(url, PostData, 5000));
		}
		if (!result.getResult().isEmpty()) {
			JSONObject json = JSON.parseObject(result.getResult());
			if (json.containsKey("errcode") && !json.getString("errcode").isEmpty()) {
				WeixinResult tresult = new WeixinResult(json);
				if (tresult.getErrCode() != 0) {
					logger.error(String.format("result:{3};url:{0};postData:{1};method:{2};", url, PostData,
							method, result.getResult()));
				}
			}
		}
		return result;
	}

}
